from regexpPredicate import *
from types import *
import os

class Language(object):
    def __init__(self, *args):
        if len(args)<2 or len(args)>3:
            raise TypeError, "__init__() takes 2 or 3 arguments (" + len(args) + " given)"
        self.shortName = args[0]
        self.longName = args[1]
        self.__name__ = self.shortName
        if len(args)==3:
            self.fileExtensions = args[2]
        else:
            self.fileExtensions = []
        self.predicates = []

    def checkFileExtension(self, fileExt):
        if fileExt.lower() in self.fileExtensions: return True
        return False

    def addPredicate(self, pred):
        if isinstance(pred, basestring):
            self.predicates.append(REPredicate.fromString(pred))
        elif isinstance(pred, CompiledREType):
            self.predicates.append(REPredicate(pred))
        elif isinstance(pred, FunctionType):
            self.predicates.append(pred)
        else:
            raise TypeError, "addPredicate() takes only strings, compile RE types, or functions"

    #true if one predicate returns true
    def checkPredicates(self, filename):
        for pred in self.predicates:
            if pred(filename):
                return True
        return False

    def __str__(self):
        return self.longName

    def __repr__(self):
        if len(self.fileExtensions)>0:
            return "<Language '"+ self.shortName +"' " + str(self.fileExtensions) + ">"
        else:
            return "<Language '"+ self.shortName +"'>"
        

languages = [('ada', 'Ada', [".a",".ada",".adb",".ads"]),
             ('applescript', 'AppleScript',[".scpt", [".applescript"]),
             ('asp', 'ASP', [".asp"]),
             ('assembly', 'Assembly', [".asm"]),
             ('autoconf', 'Autoconf'),
             ('automake', 'Automake'),
             ('awk', 'Awk', [".awk"]),
             ('basic', 'Basic/Visual Basic', [".bas", ".b", ".vb"]),
             ('bat', 'batch file', [".bat", ".cmd"]),
             ('c', 'C', [".c", ".h"]),
             ('c++', 'C++', [".cpp", ".c++", ".hh", ".h++"]),
             ('c#', 'C#', [".c#=", ".c#", ".cs"]),
             ('cobol', 'COBOL', [".cbl",".cob"]),
             ('coldfusion', 'ColdFusion', [".cfm", ".cfml"]),
             ('configure', 'configure script'),
             ('cpudescgcc', 'GCC machine description', [".md"]),
             ('cpudesclcc', 'LCC machine description', [".md"]),
             ('cpudescmono', 'Mono machine description', [".md"]),
             ('cpudescvcode', 'VCODE machine description', [".md"]),
             ('css', 'CSS', [".css"]),
             ('csv', 'CSV', [".csv"]),
             ('d', 'D', [".d"]),
             ('eiffel', 'Eiffel', [".e"]),
             ('erlang', 'Erlang', [".erl"]),
             ('fortran', 'Fortran', [".f", ".f77", ".f90", ".f95", ".f4", ".fo3"]),
             ('haskell', 'Haskell', [".hs", ".lhs"]),
             ('html', 'HTML', [".html", ".htm", ".shtml"]),
             ('java', 'Java', [".java", ".jav"]),
             ('javascript', 'JavaScript', [".js"]),
             ('jsp', 'JSP', [".jsp"]),
             ('lex', 'Lex', [".lex"]),
             ('limbo', 'Limbo', [".b"]),
             ('lisp', 'Lisp', [".lsp", ".cp", ".el"]),
             ('lua', 'Lua', [".lua"]),
             ('m4', 'm4', [".m4"]),
             ('makefile', 'Makefile'),
             ('mathematica', 'Mathematica', [".m"]),
             ('matlab', 'Matlab', [".m"]),
             ('modula2', 'Modula-2', [".mod"]),
             ('modula3', 'Modula-3', [".m3"]),
             ('objectivec', 'Objective C', [".m"]),
             ('ocaml', 'OCaml', [".ml"]),
             ('pascal', 'Pascal/Delphi', [".pas", ".p"]),
             ('patch', 'diff file', [".patch", ".dif", ".diff", ".pch"]),
             ('perl', 'Perl', [".pl", ".ph"]),
             ('php', 'PHP', [".php", ".php3", ".php4", ".php5"]),
             ('pod', 'Plain Old Documentation', [".pod"]),
             ('messagecatalog', 'message catalog'),
             ('postscript', 'PostScript', [".ps"]),
             ('prolog', 'Prolog', [".pl", ".pro"]),
             ('python', 'Python', [".py"]),
             ('r', 'R', [".s", ".r"]),
             ('rebol', 'REBOL', [".r"]),
             ('ruby', 'Ruby', [".rb"]),
             ('scheme', 'Scheme', [".scm", ".s"]),
             ('shell', 'Shell', [".sh"]),
             ('sgml', 'SGML', [".sgml"]),
             ('smalltalk', 'Smalltalk', [".sm", ".st"]),
             ('sql', 'SQL', [".sql"]),
             ('sml', 'Standard ML', [".sml", ".ml"]),
             ('svg', 'SVG', [".svg"]),
             ('tcl', 'Tcl', [".tcl"]),
             ('tex', 'TeX/LaTeX', [".tex", ".bib"]),
             ('texinfo', 'Texinfo', [".texinfo"]),
             ('troff', 'Troff', [".tr", ".1"]),
             ('vhdl', 'VHDL', [".vhdl", ".vhd"]),
             ('vim', 'Vim script', [".vim", ".vi"]),
             ('xml', 'XML', [".xml", ".rng", ".xsd"]),
             ('xpm', 'XPM', [".xpm"]),
             ('xslt', 'XSLT', [".xslt"]),
             ('xsub', 'XSUB', [".xs"]),
             ('xul', 'XUL', [".xul"]),
             ('yacc', 'Yacc', [".y"]),
             ('archive', 'Archive', [".tar.gz", ".tar.bz2", ".tar", ".zip", ".tgz"])]
              

languageDict = {}
for lang in languages:
    languageDict[lang[0]] = Language(*lang)

def getFileExtensions(filename):
    name, extension = os.path.splitext(filename)
    extensions = [extension]
    while (not extension==''):
        name, extension = os.path.splitext(name)
        if extension=='': return extensions
        extensions.append(extension + extensions[-1:])
    return None

def determineLanguage(filename):
    possibleLanguages = []
    fileExtensions = getFileExtensions(filename)
    if not bool(fileExtensions):
        for language in languageDict.values():
            for fileExtension in fileExtensions:
                if language.checkFileExtension(fileExtension):
                    possibleLanguages.append(language)
                    continue
    if len(possibleLanguages)==1:
        return str(possibleLanguages[0])
    if len(possibleLanguages)>1:
        pass
